package model

import (
	"errors"
	"regexp"
	"time"

	"github.com/bwmarrin/snowflake"
	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"
)

var node *snowflake.Node

type User struct {
	gorm.Model
	Name     string `gorm:"default:''"`
	Email    string `gorm:"type:varchar(100);uniqueIndex"`
	Password string
	Avatar   string `gorm:"size:255;default:''"` // 新增头像字段
	Role     string `gorm:"default:'user'"`
	JoyImg   string `gorm:"size:255;default:''"`
	JoyName  string `gorm:"size:255;default:''"`
	JoyTitle string `gorm:"size:255;default:''"`
	Credit	 uint64 `gorm:"default:0"`
}

func init() {
	var err error
	node, err = snowflake.NewNode(1)
	if err != nil {
		panic("failed to initialize snowflake node")
	}
}

func (u *User) BeforeCreate(tx *gorm.DB) error {
	u.ID = uint(node.Generate().Int64())
	u.CreatedAt = time.Now()
	u.UpdatedAt = time.Now()

	// 如果用户名为空，则设置为邮箱
	if u.Name == "" {
		u.Name = u.Email
	}

	// 密码强度验证
	if err := u.ValidatePassword(); err != nil {
		return err
	}

	// 密码加密
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
	if err != nil {
		return err
	}
	u.Password = string(hashedPassword)

	return nil
}

// ValidatePassword 验证密码强度
func (u *User) ValidatePassword() error {
	if len(u.Password) < 8 {
		return errors.New("密码至少需要8位")
	}

	// 至少包含一个数字
	hasNumber := regexp.MustCompile(`[0-9]`).MatchString(u.Password)
	// 至少包含一个小写字母
	hasLower := regexp.MustCompile(`[a-z]`).MatchString(u.Password)
	// 至少包含一个大写字母
	hasUpper := regexp.MustCompile(`[A-Z]`).MatchString(u.Password)

	if !hasNumber || !hasLower || !hasUpper {
		return errors.New("密码必须包含大小写字母和数字")
	}

	return nil
}

// CheckPassword 验证密码是否正确
func (u *User) CheckPassword(password string) bool {
	err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
	return err == nil
}

func (m *defaultUserModel) UpdatePassword(id int, newPassword string) error {
	// 加密新密码
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost)
	if err != nil {
		return err
	}

	// 更新数据库
	return m.db.Model(&User{}).
		Where("id = ?", id).
		Update("password", string(hashedPassword)).
		Error
}

func (m *defaultUserModel) AddCredits(id int, credits int) error {
	return m.db.Model(&User{}).
		Where("id = ?", id).
		Update("credit", gorm.Expr("credit + ?", credits)).
		Error
}

func ( m *defaultUserModel) ReduceCredits(id int, credits int) error {
	return m.db.Model(&User{}).
		Where("id = ?", id).
		Update("credit", gorm.Expr("credit - ?", credits)).
		Error
}

// UserModel 用户模型接口
type UserModel interface {
	Create(user *User) error
	FindByEmail(email string) (*User, error)
	FindById(id int) (*User, error)
	Update(id int, data map[string]interface{}) error
	UpdateAvatar(id int, avatarURL string) error
	ListJoyImg(pagenum int, pagesize int) ([]*JoyImg, error)
	GetJoyInfo(id int) (*JoyImg, error)
	UpdateJoyInfo(id int, joyName string, joyTitle string, joyid int) (*JoyImg, error)
	UpdatePassword(id int, newPassword string) error
	AddCredits(id int, credits int) error
	ReduceCredits(id int, credits int) error
}
